﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Gmantis.Controls.Chart
{
    public class PieRenderer : BasePieRenderer, IView2DRenderer, IRenderer
    {
        // Fields
        private int _ncols;
        private int _nrows;
        private Size _sz = new Size();
        private object DefSymbol = new PieSlice();

        // Methods
        public PieRenderer()
        {
            base.Symbol = this.DefSymbol;
        }

        UIElement[] IView2DRenderer.Generate()
        {
            int nser = this._dataInfo.nser;
            int npts = this._dataInfo.npts;
            if ((nser == 0) || (npts == 0))
            {
                return null;
            }
            List<UIElement> objects = new List<UIElement>();
            int num3 = 0;
            int num4 = 0;
            double width = this._sz.Width;
            double height = this._sz.Height;
            double num7 = width / ((double)this._ncols);
            double num8 = height / ((double)this._nrows);
            double num9 = 0.5 * Math.Min((double)(width / ((double)this._ncols)), (double)(height / ((double)this._nrows)));
            double naN = double.NaN;
            double startingAngle = 0.0;
            SweepDirection clockwise = SweepDirection.Clockwise;
            bool flag = false;
            Chart chart = base.Chart;
            double d = 0.0;
            if (chart != null)
            {
                startingAngle = PieOptions.GetStartingAngle(chart);
                clockwise = PieOptions.GetDirection(chart);
                flag = base.Chart.ChartType == ChartType.PieStacked;
                naN = PieOptions.GetOffset(chart);
                d = PieOptions.GetInnerRadius(chart);
            }
            if (double.IsNaN(naN))
            {
                naN = base.Offset;
            }
            if (double.IsNaN(d) || (d == 0.0))
            {
                d = base.InnerRadius;
            }
            for (int i = 0; i < nser; i++)
            {
                Point point;
                double radiusX = num9 * base.Radius;
                double inner = d;
                if (flag)
                {
                    inner = (((double)i) / ((double)nser)) * radiusX;
                    radiusX *= ((double)(i + 1)) / ((double)nser);
                    inner /= radiusX;
                }
                point = new Point((num4 - (0.5 * this._ncols)) + 0.5, (num3 - (0.5 * this._nrows)) + 0.5);
                point.X = (num7 * point.X) + (0.5 * width);
                point.Y = (num8 * point.Y) + (0.5 * height);

                IDataSeriesInfo info = base.Series[i];
                DataSeries item = info as DataSeries;
                item.Children.Clear();
                objects.Add(item);
                double num16 = this._dataInfo.SumsAbs[i];
                double[,] values = info.GetValues();
                if (!string.IsNullOrEmpty(item.Label))
                {
                    DataTemplate seriesLabelTemplate = null;
                    if (chart != null)
                    {
                        seriesLabelTemplate = PieOptions.GetSeriesLabelTemplate(chart);
                    }
                    UIElement el = null;
                    if (seriesLabelTemplate != null)
                    {
                        el = seriesLabelTemplate.LoadContent() as UIElement;
                        FrameworkElement element2 = el as FrameworkElement;
                        if (element2 != null)
                        {
                            element2.DataContext = item;
                        }
                    }
                    if (el == null)
                    {
                        TextBlock block = new TextBlock
                        {
                            Text = item.Label
                        };
                        IRenderer renderer = this;
                        Control visual = renderer.Visual as Control;
                        if (visual != null)
                        {
                            block.FontFamily = visual.FontFamily;
                            block.FontSize = visual.FontSize;
                            block.FontStretch = visual.FontStretch;
                            block.FontStyle = visual.FontStyle;
                            block.FontWeight = visual.FontWeight;
                        }
                        el = block;
                    }
                    Size size = Utils.GetSize(el);
                    Canvas.SetLeft(el, point.X - (0.5 * size.Width));
                    if ((size.Height + radiusX) > (0.5 * num8))
                    {
                        radiusX = (0.5 * num8) - size.Height;
                    }
                    if (flag)
                    {
                        Canvas.SetTop(el, (point.Y - (radiusX * inner)) - size.Height);
                    }
                    else
                    {
                        Canvas.SetTop(el, (point.Y - radiusX) - size.Height);
                    }
                    objects.Add(el);
                }
                double angle = startingAngle;
                double num18 = 0.0;
                if (naN > 0.0)
                {
                    num18 = naN * radiusX;
                    radiusX *= 1.0 - naN;
                }
                int num19 = (values != null) ? values.GetLength(1) : 0;
                for (int j = 0; j < num19; j++)
                {
                    double num21 = values[0, j];
                    if (!double.IsNaN(num21) && (num21 != 0.0))
                    {
                        ShapeStyle shapeStyle = base.StyleGen.GetStyle(j);
                        double sweep = (Math.Abs(num21) / num16) * 360.0;
                        if (sweep != 0.0)
                        {
                            if (clockwise == SweepDirection.Counterclockwise)
                            {
                                sweep = -sweep;
                            }
                            Point center = point;
                            if ((num18 > 0.0) && (sweep != 360.0))
                            {
                                double num23 = 0.017453292519943295 * (angle + (0.5 * sweep));
                                center.X += num18 * Math.Cos(num23);
                                center.Y += num18 * Math.Sin(num23);
                            }
                            PieRenderContext rc = new PieRenderContext();
                            if (sweep < 0.0)
                            {
                                rc.PieInfo = new PieInfo(center, radiusX, radiusX, inner, angle + sweep, -sweep, 0.0, 0.0);
                            }
                            else
                            {
                                rc.PieInfo = new PieInfo(center, radiusX, radiusX, inner, angle, sweep, 0.0, 0.0);
                            }
                            DataPoint dp = item.CreateDataPoint(i, j);
                            IPlotElement pe = null;
                            if ((item.Symbol is PlotElement) && ((IPlotElement)item.Symbol).IsCompatible(this))
                            {
                                pe = ((PlotElement)item.Symbol).Clone() as IPlotElement;
                            }
                            if ((pe == null) && (base.Symbol is PlotElement))
                            {
                                pe = ((PlotElement)base.Symbol).Clone() as IPlotElement;
                            }
                            base.RenderElement(objects, pe, item, rc, shapeStyle, dp);
                            if (item.ReadLocalValue(DataSeries.SymbolStrokeProperty) != DependencyProperty.UnsetValue)
                            {
                                ((PlotElement)pe).Stroke = item.SymbolStroke;
                            }
                            if (item.ReadLocalValue(DataSeries.SymbolStrokeThicknessProperty) != DependencyProperty.UnsetValue)
                            {
                                ((PlotElement)pe).StrokeThickness = item.SymbolStrokeThickness;
                            }
                            angle += sweep;
                        }
                    }
                }
                if (!flag)
                {
                    num4++;
                    if (num4 >= this._ncols)
                    {
                        num4 = 0;
                        num3++;
                    }
                }
            }
            return objects.ToArray();
        }

        Rect IView2DRenderer.Measure(Size sz)
        {
            if (this._sz != sz)
            {
                this._sz = sz;
            }
            Rect rect = new Rect();
            base.AnalyzeData(false);
            this._nrows = 0;
            this._ncols = 0;
            int nser = this._dataInfo.nser;
            int npts = this._dataInfo.npts;
            if (((nser > 0) && (npts > 0)) && this.PerformLayout(nser, sz))
            {
                rect.X = -0.5 * this._ncols;
                rect.Width = this._ncols;
                rect.Y = -0.5 * this._nrows;
                rect.Height = this._nrows;
            }
            return rect;
        }

        private bool PerformLayout(int nPies, Size sz)
        {
            this._ncols = nPies;
            this._nrows = 1;
            if (nPies < 1)
            {
                return false;
            }
            if ((sz.Height <= 0.0) || (sz.Width <= 0.0))
            {
                return false;
            }
            if (base.Chart.ChartType == ChartType.PieStacked)
            {
                nPies = 1;
            }
            double num = 0.0;
            for (int i = 1; i <= nPies; i++)
            {
                int num3 = (nPies + (i - 1)) / i;
                double num4 = sz.Width / ((double)i);
                double num5 = sz.Height / ((double)num3);
                if (num5 < num4)
                {
                    num4 = num5;
                }
                if (num4 > num)
                {
                    num = num4;
                    this._ncols = i;
                    this._nrows = num3;
                }
            }
            return true;
        }

        // Properties
        AxisStyle IView2DRenderer.Axis
        {
            get
            {
                return AxisStyle.None;
            }
        }
    }
}
